Windows Server 2019 EC2インスタンスでSSHサーバーを有効にする
しばたです。
「ドキュメントがあるから余裕でしょ。」と高を括っていたら予想以上にハマったので本記事で共有します。
追記
前提
WindowsではWindows 10 Fall Creators Update(1709)からOSに標準でOpenSSHのポートであるWin32-OpenSSHが組み込まれており、サーバーOSもその流れを受けて半期チャネルではWindows Server version 1803から、長期サービスチャネルではWindows Server 2019からOSにOpenSSHのサーバーおよびクライアント機能が組み込まれています。
SSHサーバー(sshd
)の機能はデフォルトではオフにされており、SSHサーバーを利用するには機能を有効にして所定の初期設定を行う必要があります。
作業手順
作業手順は公式にはMicrosoft Docsに記載されています。
基本的にはこちらの手順に従えば良いのですが、Windows独自の仕様やOpenSSHのバージョンによる変更点がそこそこあり、知ってしまえばどうということはないのですが、初見ではハマってしまうポイントが結構ありました。
また、本記事ではEC2インスタンス上にSSHサーバーを立てるので鍵設定の部分に関しては独自の手順を取り入れています。
やってみた
それでは本題に入ります。
本記事ではRDPを使いAdministratorでOSにログインした状態をスタート地点とし、Windows PowerShellのコンソール上で各種作業を進めていきます。
1. 機能の有効化
はじめにAdd-WindowsCapability
コマンドレットを使いSSHサーバーの機能を有効にし、sshdサービスの初期設定を行います。
# Install the OpenSSH Server
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
# Configure sshd service setting
Start-Service sshd
Set-Service -Name sshd -StartupType 'Automatic'
2. sshd_configの設定変更
Windows Server 2019のsshdではsshd_config
は%programdata%\ssh\sshd_config
にあります。
(sshd.exe
のあるディレクトリでは無いので注意。Ver.1.0.0.0-betaからの変更点になります。)
デフォルトでは公開鍵認証とパスワード認証が有効になっています。
本記事では公開鍵認証のみを明示して許可する設定に変更します。
# 残念ながらWindowsにはsedが標準搭載されていないので気合で sshd_config を修正
$sshdConfigPath = Join-Path $env:ProgramData 'ssh\sshd_config'
Get-Content $sshdConfigPath -Encoding Ascii -Raw |
ForEach-Object {
$c = $_ -replace '#PubkeyAuthentication', 'PubkeyAuthentication'
$c = $c -replace '#PasswordAuthentication yes', 'PasswordAuthentication no'
$c | Out-File -FilePath $sshdConfigPath -Encoding ascii
}
# サービス再起動
Restart-Service sshd
3. 公開鍵設定
次に公開鍵の設定を行います。
通常のSSHサーバーであればssh-keygen
などを使い鍵を生成しますが、今回はEC2インスタンスなのでキーペアが既に存在しています。
EC2キーペアの公開鍵はインスタンスメタデータから取得できますのでこれをauthorized_keys
に設定してやります。
ここでWindowsの独自仕様としてsshd_config
に以下の記述がされており、Administrators
グループの公開鍵は%programdata%\ssh\administrators_authorized_keys
に設定する必要があります。
(本件に該当するGitHubのIssueはこちら)
Match Group administrators
AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys
administrators_authorized_keys
の設定は以下のコマンドで行います。
# インスタンスメタデータから公開鍵を取得し administrators_authorized_keys に設定
$administratorsKeyPath = Join-Path $env:ProgramData 'ssh\administrators_authorized_keys'
Invoke-RestMethod -Uri http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key/ |
Out-File -FilePath $administratorsKeyPath -Encoding ascii
そして作成したばかりのadministrators_authorized_keys
には不要なアクセス権(Authenticated Users
のアクセス権)が付与されているのでこれを除外します。
# フォルダのアクセス権を取得
$acl = Get-Acl $administratorsKeyPath
# アクセス権の継承を解除
$acl.SetAccessRuleProtection($true,$true)
# アクセスルールを除去
$removeRule = $acl.Access | Where-Object { $_.IdentityReference -eq 'NT AUTHORITY\Authenticated Users' }
$acl.RemoveAccessRule($removeRule)
# アクセス権を更新
$acl | Set-Acl -Path $administratorsKeyPath
追記 : インスタンスメタデータサービスV2 (IMDSv2)必須の場合
インスタンスメタデータサービスV2の利用が必須の場合、最初にトークンを取得してからメタデータにアクセスする必要があります。
このため公開鍵の取得を以下の様にしてください。
# IMDSv2に対応した形でインスタンスメタデータを取得し、administrators_authorized_keysファイルに書き込む
$administratorsKeyPath = Join-Path $env:ProgramData 'ssh\administrators_authorized_keys'
$params = @{
Headers = @{
"X-aws-ec2-metadata-token" = Invoke-RestMethod 'http://169.254.169.254/latest/api/token' -Method Put -Headers @{ "X-aws-ec2-metadata-token-ttl-seconds" = 60 }
}
Uri = 'http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key/'
}
Invoke-RestMethod @params | Out-File -FilePath $administratorsKeyPath -Encoding ascii
4. (Optional) デフォルトシェルの変更
Windows版OpenSSHのデフォルトシェルはコマンドプロンプトです。
シェルの指定はレジストリにあり、以下の様にするとデフォルトシェルをPowerShellに変更可能です。
# change default shell
New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -PropertyType String -Force
以上で設定は完了です。
接続確認
最後にSSHクライアントからこのサーバーに接続して動作確認をしてみます。
無事接続され、シェルもWindows PowerShellになっています。
補足
こうやって記事にするとあっさりした手順で済んでいますが、記事を書くに至るまでには結構調査の時間がかかりました。
補足として調査の役に立ったTipsを紹介します。
デバッグログ
SSHサーバー側のログ設定はsshd_config
に記載されており、SyslogFacility
でログの出力先を、LogLevel
でログの詳細度を設定できます。
サーバー側のログ設定を以下の様にすると詳細な情報を直ちに取得できます。
SyslogFacility LOCAL0
LogLevel DEBUG3
- SyslogFacility LOCAL0
- ログの出力先をローカルファイルに変更 (ログは
%programdata%\ssh\log\
に吐かれる)
- ログの出力先をローカルファイルに変更 (ログは
- LogLevel DEBUG3
- 詳細なログ出力に変更。DEBUG3未満のレベルだと欲しい情報が取れないことが多かった
OpenSSHUtils モジュール
各種ファイルのアクセス権をよしなに設定してくれるOpenSSHUtilsがPowerShell Galleryで公開されています。
# OpenSSHUtils モジュールのインストール
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
Install-Module -Name OpenSSHUtils -Scope CurrentUser -Force -SkipPublisherCheck
以前は同等のモジュールファイルがsshdと同じディレクトリにあった記憶があるのですが、いつの間にか独立したモジュールになっていました。
このモジュールにあるRepair-AuthorizedKeyPermission
コマンドレットを使うとauthorized_keys
ファイルのアクセス権を設定できるのですが、残念ながらauthorized_keys
の置き場所が~\.ssh\authorized_keys
決め打ちとなっており、今回のadministrators_authorized_keys
では使用できませんでした。
本記事では使用しませんでしたが環境によってはこのモジュールを使うとより楽にSSHの設定が可能になるはずです。